package com.loup.jdbc;

import com.loup.handler.SimpleTypeHandler;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.*;
import java.util.Arrays;
import java.util.Map;

/**
 * 创建数据库连接
 * Created by loup on 2018/4/28.
 */
public class LoupConnection<T> {

    public Connection getConnection(String url,String className,String user,String password) throws Exception {
        Class.forName(className);
        return DriverManager.getConnection(url,user,password);
    }

    /**
     * @param sql        sql语句
     * @param returnType 返回类型
     * @param args       参数
     * @return
     */
    public Object handler(Connection conn, String sql, Class<T> returnType, Object... args) {
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            if (args != null && args.length > 0) {
                for (int i = 0; i < args.length; i++) {
                    setParamValue((i + 1), args[i], pstmt);
                }
            }

            pstmt.execute();

            ResultSet rs = pstmt.getResultSet();

            Map<String, String> porpertyColumnMapper = SimpleTypeHandler.getPropertyClounmMapper(returnType.getName());
            DefaultObjectFactory defaultObjectFactory = new DefaultObjectFactory();
            T obj = defaultObjectFactory.create(returnType);
            while (rs.next()) {
                setValue(returnType,obj,rs,porpertyColumnMapper);
            }

            return obj;

        } catch (SQLException e) {
            System.out.println("get connection failed:{}" + Arrays.toString(e.getStackTrace()));
        } finally {
            try {
                if (conn != null) {
//                    conn.commit();
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public void setParamValue(int i, Object object, PreparedStatement ps) throws SQLException {
        if (object instanceof String) {
            ps.setString(i, object.toString());
        } else if (object instanceof Integer) {
            ps.setInt(i, (Integer) object);
        } else if (object instanceof Date) {
            ps.setDate(i, (Date) object);
        } else if (object instanceof BigDecimal) {
            ps.setBigDecimal(i, (BigDecimal) object);
        }
    }

    public void setValue(Class rt,Object obj, ResultSet rs, Map<String, String> porpertyColumsMapper) {

        Field[] fields = rt.getDeclaredFields();
        for (Field field : fields) {
            try {
                Method method = rt.getMethod("set" + upperFirstField(field.getName()),field.getType());
                method.invoke(obj, rs.getObject(porpertyColumsMapper.get(field.getName())));

                //字段设置值得另一种方式
                field.setAccessible(true);
                field.set(obj,rs.getObject(porpertyColumsMapper.get(field.getName())));

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void closeConnection(Connection conn) {
        try {
            conn.close();
        } catch (SQLException e) {
            System.out.println("close connection faileds");
            e.printStackTrace();
        }
    }

    /**
     * 将字符串的首个字母变为大写
     *
     * @param str
     * @return
     */
    public String upperFirstField(String str) {
        if (str == null || str.length() <= 0) {
            return null;
        }
        String first = str.substring(0, 1).toUpperCase();
        return first + str.substring(1);

    }


}
